﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Diagnostics;
using System.Reflection;
using System.Security.Cryptography;
using System.Text;
using System.Xml;

namespace SystemX
{
	/// <summary>
	/// Utils for Web application
	/// </summary>
	public static partial class Utils
	{
		/// <summary>
		/// Convert a datarow object to a Dictionary
		/// </summary>
		/// <returns></returns>
		public static Dictionary<string, object> ToDictionary(DataRow dr)
		{
			Dictionary<string, object> retVal = new Dictionary<string, object>();
			DataTable dt = dr.Table;
			int i = 0;
			foreach (DataColumn col in dt.Columns)
			{
				string colName = col.ColumnName;
				if (string.IsNullOrEmpty(colName))
				{
                    colName = String.Format("Col{0}", i);
				}
				retVal.Add(colName, dr[i]);
				i++;
			}
			return retVal;
		}//endof ToDictionary

		/// <summary>
		/// whether the SystemX.dll was built in the debug mode.
		/// </summary>
		public static bool IsDebug
		{
			get
			{
#if !DEBUG
				return false;
#else
				return true;
#endif

			}
		}

		#region Is Mono/Linux

		private static int mono = 0;
		/// <summary>
		/// Gets a value indicating whether we're running under Mono.
		/// </summary>
		/// <value><c>true</c> if Mono; otherwise, <c>false</c>.</value>
		public static bool IsMono
		{
			get
			{
				if (mono == 0)
				{
					if (Type.GetType("Mono.Runtime") != null)
						mono = 1;
					else
						mono = 2;
				}

				return mono == 1;
			}
		}

		/// <summary>
		/// Gets a value indicating whether we're running under Linux or a Unix variant.
		/// </summary>
		/// <value><c>true</c> if Linux/Unix; otherwise, <c>false</c>.</value>
		public static bool IsLinux
		{
			get
			{
				int p = (int)Environment.OSVersion.Platform;
				return ((p == 4) || (p == 128));
			}
		}

		#endregion

		#region is value type or string
		public static bool ISValueType<T>(this T obj) {
			return obj.GetType().IsValueType;
		}
		public static bool IsString<T>(this T obj) {
			return obj.GetType()== typeof(string);
		}
		public static bool IsValueTypeOrString<T>(this T obj) {
			return obj.ISValueType() || obj.IsString();
		}
		/// <summary>
		/// Detect whether a string instance can be parse to xml document.
		/// This method use LoadXml(string) to do the detect job.
		/// </summary>
		/// <param name="obj"></param>
		/// <returns></returns>
		public static bool IsXMLable(this string obj)
		{
			var xmlDoc = new XmlDocument();
			try
			{
				xmlDoc.LoadXml(obj);
				return true;
			}
			catch (Exception ex)
			{
				return false;
			}
		}
		#endregion

		public static string GetCaller() {
			var caller = string.Empty;
			var stackTrace = new StackTrace();
			var stackFrame = stackTrace.GetFrame(1);
			MethodBase methodBase = stackFrame.GetMethod();
			caller = String.Format("{0}-{1}", methodBase.DeclaringType.FullName, methodBase.Name);
			return caller;
		}
		/// <summary>
		/// available memory
		/// </summary>
		/// <returns></returns>
		public static long GetAvailableMemory()
		{
			using (PerformanceCounter performanceCounter = new PerformanceCounter("Memory", "Available MBytes"))
			{
				return performanceCounter.RawValue;
			}
		}

        #region gravatar
        public const string GravatarUrl = "http://www.gravatar.com/avatar.php?gravatar_id=";

        /// <summary>
        /// Get Gravatar image url
        /// </summary>
        /// <param name="email"></param>
        /// <param name="size"></param>
        /// <param name="rating"></param>
        /// <returns></returns>
        public static string GetGravatar(string email, int size, string rating)
        {
            email = email.ToLower();
            email = GetMd5Hash(email);

            if (size < 1 | size > 600)
            {
                throw new ArgumentOutOfRangeException("size",
                    "The image size should be between 20 and 80");
            }

            rating = rating.ToLower();
            if (rating != "g" & rating != "pg" & rating != "r" & rating != "x")
            {
                throw new ArgumentOutOfRangeException("rating",
                    "The rating can only be one of the following: g, pg, r, x");
            }

            return string.Format("{0}{1}&s={2}&r={3}", GravatarUrl, email, size, rating);
        }
        /// <summary>
        /// Get MD5 HASH for a string
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public static string GetMd5Hash(string input)
        {
            // Create a new instance of the MD5CryptoServiceProvider object.
            MD5 md5Hasher = MD5.Create();

            // Convert the input string to a byte array and compute the hash.
            byte[] data = md5Hasher.ComputeHash(Encoding.Default.GetBytes(input));

            // Create a new Stringbuilder to collect the bytes
            // and create a string.
            StringBuilder sBuilder = new StringBuilder();

            // Loop through each byte of the hashed data
            // and format each one as a hexadecimal string.
            for (int i = 0; i < data.Length; i++)
            {
                sBuilder.Append(data[i].ToString("x2"));
            }

            return sBuilder.ToString();  // Return the hexadecimal string.
        }
        #endregion
    }
}
